﻿using System.Text.Encodings.Web;
using System.Text.Unicode;
using Microsoft.AspNetCore.Mvc.Infrastructure;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Hosting;
using PmSoft.Caching;
using PmSoft.Caching.Redis;
using PmSoft.Utilities;
using PmSoft.Events;
using PmSoft.Quartz;
using PmSoft.FileStorage;
using StackExchange.Redis;
using Microsoft.Extensions.Caching.StackExchangeRedis;
using System.Net;
using PmSoft.Logging;
//using PmSoft.Repositories;
//using PmSoft.DBContext;
//using PmSoft.Log4Net;
//using PmSoft.Events;
//using PmSoft.Logging.Repositories;
//using PmSoft.Logging;
//using PmSoft.Caching.Redis;
//using PmSoft.Utilities;
//using PmSoft.Quartz;
//using PmSoft.FileStore;

namespace PmSoft
{
    public static class Builder
    {
        /// <summary>
        /// 注入基础组件
        /// </summary>
        /// <param name="services"></param>
        /// <param name="configuration"></param>
        public static void AddPmSoftFrameWork(this IServiceCollection services, IConfiguration configuration, IHostEnvironment environment)
        {
            //配置log4net 写入数据库连接
            MySQLAppender.DbConnection = configuration.GetConnectionString("LogDbConnection");

            services.AddSingleton(HtmlEncoder.Create(UnicodeRanges.All));

            //用户请求上下文访问器
            services.AddHttpContextAccessor();

            //控制器方法上下文访问器
            services.AddSingleton<IActionContextAccessor, ActionContextAccessor>();

            //添加分布式缓存
            services.Configure<RedisCacheOptions>(configuration.GetSection("RedisCacheOptions"));
            services.AddStackExchangeRedisCache(options =>
            {
                //options.InstanceName = $"{(configuration.GetValue<string>("RedisCache:InstanceName") ?? "PmSoft")}:";
                //  options.Configuration = configuration.GetValue<string>("RedisCache:Connection");
                var endPoints = configuration.GetSection("RedisCacheOptions:ConfigurationOptions:EndPoints").Get<string[]>() ?? new string[0];
                foreach (var endPoint in endPoints)
                {
                    options.ConfigurationOptions?.EndPoints.Add(EndPointCollection.TryParse(endPoint));
                }

                //options.ConfigurationOptions = new ConfigurationOptions()
                //{
                //    EndPoints = { { "192.168.0.16", 6381 }, { "192.168.0.16", 6382 }, { "192.168.0.16", 6383 } },
                //    Password = "123456",
                //    // ServiceName = "mymaster",
                //    // DefaultDatabase = 0,
                //    //AllowAdmin = true,
                //    AbortOnConnectFail = false,
                //    KeepAlive = 180,
                //    //TieBreaker = "",
                //    //CommandMap = CommandMap.Create(new HashSet<string>//哨兵模式， EXCLUDE a few commands
                //    //{
                //    //    "INFO", "CONFIG", "CLUSTER","PING", "ECHO", "CLIENT"
                //    //}, available: false),
                //    //CommandMap = StackExchange.Redis.CommandMap.Sentinel,
                //};

            });
            //添加自定义Redis缓存类
            services.AddPmSoftRedisCache();


            //注册默认缓存服务
            services.Configure<CacheServiceOptions>(configuration.GetSection("CacheService"));
            services.AddDefaultCacheService();

            //日志
            services.AddLogging(builder =>
            {
                builder
                .AddFilter("Microsoft", LogLevel.Warning)
                .AddConsole()
                .AddDebug()
                .AddLog4Net(Path.Combine("Config", "log4net.config"), true);
            });

            //定时器
            services.AddQuartz();

            //注册事件总线
            services.AddSingleton<IEventBus, LocalEventBus>();
            services.AddSingleton<LocalEventBus>();

            //注册文件仓库
            services.Configure<MinIoOptions>(configuration.GetSection("ThreePartyOptions:Minio"));
            services.AddFileStorage();

            //IP归属地
            //services.AddSingleton<IPSearcher>(c => new DbSearcher(Path.Combine(environment.ContentRootPath, "Config", "ip2region.db")));
            services.AddSingleton<IPSearcher>(c => new QQZengIp(Path.Combine(environment.ContentRootPath, "Config", "qqzeng-ip-utf8.dat")));

            //程序集注入
            services.AutoRegisterServicesFromAssembly("PmSoft.Framework");
        }
    }
}
